查看原文
其他

骆小刚:Linux后台服务启动方式systemd、daemon、nohup大比拼

骆小刚 Linux阅码场 2021-01-31


作者简介

骆小刚,现就职于深圳市普康电子有限公司,高级软件工程师。负责arm下u-boot、kernel开发,APP框架搭建,底层软件开发,算法开发,性能优化等。对开源软件有浓厚兴趣。

本文主要用实例剖析systemd、daemon()、nohup启动服务的差异。

环境:ubuntu 1804 x86_64, linux 5.0,  gcc 8.3.0 


1. systemd启动服务

systemd是最新linux发行版管理后台的服务的默认形式,用以取代原有的init。

1.1 编写服务程序

vim simple-server.c

gcc simple-server.c  -o simple-server

1.2 配置服务

编辑服务配置文件simple-server.service

vim simple-server.service 

解析:

[Unit] :服务单元

Description:对该服务进行简单的描述

[Service]:服务运行时行为配置

ExecStart:程序的完整路径

Restart:重启配置,no、always、on-success、on-failure、on-abnormal、on-abort、on-watchdog

[Install]:安装配置

WantedBy:多用户等


其他配置选项请参考:

https://www.freedesktop.org/software/systemd/man/systemd.service.html

将配置拷贝到/lib/systemd/system/目录下:

sudo cp simple-server.service /lib/systemd/system/

1.3 启用服务

sudo systemctl enable simple-server

会创建一个指向配置文件/lib/systemd/system/simple-server.service的符号链接

/etc/systemd/system/multi-user.target.wants/simple-server.service

1.4 开启服务

sudo systemctl start simple-server

1.5 服务状态

1.5.1服务与终端的关系

pstree

可以看到systemd启动的服务直接是pid=1的systemd进程的子进程。

可以看到服务程序忽略了SIGPIPE信号。

服务没有控制终端(tty为“?”)。


1.5.3 服务的运行日志

sudo lsof -p 6213

用lsof可以看到服务的用户为root,当前目录和根目录都是“/”,输入被重定向到/dev/null,输出和出错被重定向到socket。


1.5.4 服务的运行状态

sudo systemctl status simple-server

我可以看到simple-server服务已经loaded,并且处于active状态。还可以看到PID、Tasks数量、服务管理日志等。


1.6 关闭服务

sudo systemctl stop simple-server

1.7 停用服务

 sudo systemctl disable simple-server


2. daemon启动服务

2.1 编写代码

vim daemon.c 

gcc  daemon.c -o daemon

 

2.2 启动服务

./daemon

2.3 服务状态


2.3.1 服务与终端的关系

服务把自己设置为会话首领,父进程是当前用户级的systemd(subreaper ),完全脱离终端。


2.3.2 服务的信号处理

ps -C daemon s

没有屏蔽信号。

控制终端tty为“?”


2.3.3 服务的运行日志

当前目录和根目录都是“/”,用户为普通用户,输入、输出、出错都重定向到/dev/null

2.4 停止服务

killall  daemon 


3. nohup 启动服务

3.1 编写代码

vim nohup.c

gcc nohup.c -o nohup


3.2 启动服务

nohup命令启动这个名字也叫nohup的程序

(注意后面一个nohup是上面写的那个很简单的程序的名字)

nohup ./nohup


3.3 服务状态

3.3.1服务与终端的关系

服务的父进程是启动该服务的bash,和bash在一个会话组。


3.3.2 服务的信号处理

普通用户,屏蔽SIGHUP信号,依赖终端bash。由于屏蔽了SIGHUP,终端关闭的时候,会忽略终端发送的SIGHUP信号,继续运行服务。


3.3.3服务的运行日志

输入被重定向到/dev/null,输出、出错为当前目录下的nohup.out,格式没有带时间,不便于分析问题。

3.4 服务关闭

killall nohup


4. 总结

4.1 后台运行服务的基本需求

基本需求:

  •  脱离终端(终端关闭时,服务不能关闭)

  •  处理输入、输出、出错描述符

4.1.1  systemd

自己本身就是一个init或者user级的subreaper;

系统级systemd启动的服务以root权限运行;

重定向输入到/dev/null,输出、出错通过socket发给系统日志模块。


4.1.2 daemon

通过fork后父进程exit,让子进程托孤给subreaper,实现在后台运行服务。

重定向输入、输出、出错到/dev/null.

源码参考:

https://github.com/lattera/glibc/blob/master/misc/daemon.c

4.1.3 nohup

  通过忽略终端关闭时的广播信号SIGHUP,实现在后台运行服务。

重定向输入到/dev/null,输出、出错重定向到当前目录下的nohup.out文件,


4.2 后台运行服务的高级需求

高级需求:

  • 方便分析问题的服务运行日志记录

  •  服务管理的日志

  •  异常退出时可以根据需要重新启动

daemon不能实现上面的高级需求。

nohup 只能记录服务运行时的输出和出错日志。

只有systemd能够实现上述所有需求。

 


默认的日志中增加了时间、用户名、服务名称、PID等,非常人性化。

还能看到服务运行异常退出的日志。

还能通过/lib/systemd/system/下的配置文件定制各种需求。

还有非常非常多强大的功能等着你去探索:

https://www.freedesktop.org/software/systemd/man/systemd.html


4.3 systemd是目前linux管理后台服务的主流方式






Linux阅码场原创精华文章汇总

更多精彩,尽在"Linux阅码场",扫描下方二维码关注

点一点右下角”在看”,为阅码场打Call~

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存